import { toRef, reactive, ref, h } from 'vue';
import {
  AppCtrlEvents,
  IAppCtrlControllerBase,
  MobMapCtrlController,
  MobTabExpPanelCtrlController,
  MobTabViewPanelCtrlController,
  ICtrlEventParam,
  IParam,
  MobTreeExpBarController,
  MobMapExpBarController,
} from 'ibz-core';
import {
  AppCtrlProps,
  MobMenuCtrlController,
  MobFormCtrlController,
  MobMDCtrlController,
  MobPanelController,
  MobSearchFormCtrlController,
  MobToolbarCtrlController,
  MobCalendarCtrlController,
  MobPickUpViewPanelCtrlController,
  MobTreeCtrlController,
  MobChartCtrlController,
  MobMEditViewPanelCtrlController,
  MobContextMenuCtrlController,
  MobDashboardController,
  MobPortletController,
  MobListExpBarController,
  MobWizardPanelController,
  MobStateWizardPanelController,
  MobChartExpBarController,
} from 'ibz-core';
import { ComponentBase } from '../component-base';
import { IPSControl, IPSDEMobMDCtrl } from '@ibiz/dynamic-model-api';
import { Util } from 'ibz-core';
import { AppCtrlContainer } from '../common';

/**
 * 部件组件基类
 *
 * @export
 * @class CtrlComponentBase
 */
export class CtrlComponentBase<Props extends AppCtrlProps> extends ComponentBase<AppCtrlProps> {
  /**
   * @description 部件是否加载完成
   * @type {*}
   * @memberof CtrlComponentBase
   */
  public controlIsLoaded: any;

  /**
   * @description 部件控制器
   * @protected
   * @type {IAppCtrlControllerBase}
   * @memberof CtrlComponentBase
   */
  protected c!: IAppCtrlControllerBase;

  /**
   * @description vue ref引用集合
   * @type {Map<string, any>}
   * @memberof CtrlComponentBase
   */
  public refsMap: Map<string, any> = new Map();

  /**
   * @description 部件样式名
   * @readonly
   * @type {any}
   * @memberof CtrlComponentBase
   */
  get classNames(): any {
    const { controlType, codeName } = this.c.controlInstance;
    const classNames: any = {
      'container-margin': true,
      'container-padding': true,
      'app-ctrl': true,
      [controlType?.toLowerCase()]: true,
      [Util.srfFilePath2(codeName)]: true,
    };
    const sysCss = this.c.controlInstance.getPSSysCss?.();
    if (sysCss) {
      Object.assign(classNames, { [sysCss.cssName]: true });
    }
    return classNames;
  }

  /**
   * @description 设置响应式
   * @memberof CtrlComponentBase
   */
  setup() {
    this.controlIsLoaded = toRef(this.c, 'controlIsLoaded');
    this.initReactive();
    this.emitCtrlEvent = this.emitCtrlEvent.bind(this);
    this.c.hooks.event.tap(this.emitCtrlEvent);
    this.emitCloseView = this.emitCloseView.bind(this);
    this.c.hooks.closeView.tap(this.emitCloseView);
    this.ctrlMounted = this.ctrlMounted.bind(this);
    this.c.hooks.mounted.tap(this.ctrlMounted);
  }

  /**
   * @description 初始化响应式属性
   * @memberof CtrlComponentBase
   */
  public initReactive() {
    this.c.context = reactive(this.c.context);
    this.c.viewParam = reactive(this.c.viewParam);
    this.c.navDatas = reactive(this.c.navDatas);
    this.c.viewCtx = reactive(this.c.viewCtx);
    if (this.c && this.c.actionModel) {
      this.c.actionModel = reactive(this.c.actionModel);
    }
  }

  /**
   * @description 部件初始化
   * @memberof CtrlComponentBase
   */
  init() {
    this.c.controlInit().then((result: boolean) => {
      this.emitCtrlEvent({ controlname: this.c.controlInstance?.name, action: AppCtrlEvents.INITED, data: result });
    });
  }

  /**
   * @description 部件输入属性值变更
   * @memberof CtrlComponentBase
   */
  watchEffect() {
    this.c.initInputData(this.props);
  }

  /**
   * @description 部件销毁
   * @memberof CtrlComponentBase
   */
  public unmounted(): void {
    this.c.controlDestroy();
    this.c.hooks.event.removeTap(this.emitCtrlEvent);
    this.c.hooks.closeView.removeTap(this.emitCloseView);
    this.c.hooks.mounted.removeTap(this.ctrlMounted);
    this.emitCtrlEvent({ controlname: this.c.controlInstance?.name, action: AppCtrlEvents.DESTROYED, data: true });
  }

  /**
   * @description 执行部件事件
   * @param {ICtrlEventParam} arg 事件参数
   * @memberof CtrlComponentBase
   */
  public emitCtrlEvent(arg: ICtrlEventParam) {
    this.ctx.emit('ctrlEvent', arg);
  }

  /**
   * @description 抛出关闭视图事件
   * @param {IParam} arg 事件参数
   * @memberof CtrlComponentBase
   */
  public emitCloseView(arg: IParam) {
    this.emitCtrlEvent({ controlname: this.c.controlInstance?.name, action: AppCtrlEvents.CLOSE, data: arg });
  }

  /**
   * @description 部件挂载完成
   * @param {IParam} arg 事件参数
   * @memberof CtrlComponentBase
   */
  public ctrlMounted(args?: any) {}

  /**
   * @description 根据部件类型获取部件控制器
   * @param {string} type 部件类型
   * @return {*}
   * @memberof CtrlComponentBase
   */
  public getCtrlControllerByType(type: string) {
    switch (type) {
      case 'APPMENU':
        return new MobMenuCtrlController(this.props);
      case 'TOOLBAR':
        return new MobToolbarCtrlController(this.props);
      case 'FORM':
        return new MobFormCtrlController(this.props);
      case 'SEARCHFORM':
        return new MobSearchFormCtrlController(this.props);
      case 'MOBMDCTRL':
        return new MobMDCtrlController(this.props);
      case 'PANEL':
        return new MobPanelController(this.props);
      case 'PICKUPVIEWPANEL':
        return new MobPickUpViewPanelCtrlController(this.props);
      case 'CALENDAR':
        return new MobCalendarCtrlController(this.props);
      case 'TREE':
        return new MobTreeCtrlController(this.props);
      case 'CHART':
        return new MobChartCtrlController(this.props);
      case 'MAP':
        return new MobMapCtrlController(this.props);
      case 'CONTEXTMENU':
        return new MobContextMenuCtrlController(this.props);
      case 'TABEXPPANEL':
        return new MobTabExpPanelCtrlController(this.props);
      case 'TABVIEWPANEL':
        return new MobTabViewPanelCtrlController(this.props);
      case 'MULTIEDITVIEWPANEL':
        return new MobMEditViewPanelCtrlController(this.props);
      case 'DASHBOARD':
        return new MobDashboardController(this.props);
      case 'PORTLET':
        return new MobPortletController(this.props);
      case 'LISTEXPBAR':
        return new MobListExpBarController(this.props);
      case 'WIZARDPANEL':
        return new MobWizardPanelController(this.props);
      case 'CHARTEXPBAR':
        return new MobChartExpBarController(this.props);
      case 'WIZARDPANEL_STATE':
        return new MobStateWizardPanelController(this.props);
      case 'TREEEXPBAR':
        return new MobTreeExpBarController(this.props);
      case 'MAPEXPBAR':
        return new MobMapExpBarController(this.props);
      default:
        console.log(`暂未实现${type}类型部件`);
        return null;
    }
  }

  /**
   * @description 计算目标部件所需参数
   * @param {IPSControl} controlInstance 部件模型实例
   * @return {*}
   * @memberof CtrlComponentBase
   */
  public computeTargetCtrlData(controlInstance: IPSControl, otherParams: IParam = {}) {
    const targetCtrlComponent: any = App.getComponentService().getControlComponent(
      controlInstance?.controlType,
      controlInstance?.controlStyle ? controlInstance?.controlStyle : 'DEFAULT',
      controlInstance.getPSSysPFPlugin() ? `${controlInstance.getPSSysPFPlugin()?.pluginCode}` : undefined,
    );
    this.refsMap.set(controlInstance.name, ref(null));
    const targetCtrlParams = {
      ref: this.refsMap.get(controlInstance.name),
      controlInstance: controlInstance,
      viewState: this.c.viewState,
      viewCtx: this.c.viewCtx,
      navContext: Util.deepCopy(this.c.context),
      navParam: Util.deepCopy(this.c.viewParam),
      modelService: this.c.modelService,
      modelData: controlInstance,
      previewData: this.c.previewData,
      onCtrlEvent: ({ controlname, action, data }: { controlname: string; action: string; data: any }) => {
        this.c.handleCtrlEvent(controlname, action, data);
      },
    };
    if (otherParams && Object.keys(otherParams).length > 0) {
      Object.assign(targetCtrlParams, otherParams);
    }
    return h(AppCtrlContainer, null, {
      default: () => {
        return h(targetCtrlComponent, targetCtrlParams);
      },
    });
  }

  /**
   * @description 下拉刷新
   * @param {*} event 事件源
   * @memberof CtrlComponentBase
   */
  public pullDownRefresh(event: any) {
    if (this.c.pullDownRefresh && this.c.pullDownRefresh instanceof Function) {
      this.c
        .pullDownRefresh()
        .then((response: any) => {
          event.target.complete();
        })
        .catch((error: any) => {
          event.target.complete();
        });
    }
  }

  /**
   * @description 绘制下拉刷新
   * @return {*}
   * @memberof CtrlComponentBase
   */
  public renderPullDownRefresh() {
    if (this.c.enablePullDownRefresh) {
      return (
        <ion-refresher
          slot='fixed'
          onIonRefresh={(event: any) => {
            this.pullDownRefresh(event);
          }}
        >
          <ion-refresher-content />
        </ion-refresher>
      );
    }
  }

  /**
   * @description 绘制无数据
   * @return {*}
   * @memberof CtrlComponentBase
   */
  public renderNoData() {
    return (
      <div class='no-data'>
        {this.$tl(
          (this.c.controlInstance as IPSDEMobMDCtrl)?.getEmptyTextPSLanguageRes?.()?.lanResTag,
          (this.c.controlInstance as IPSDEMobMDCtrl).emptyText,
        ) || this.$tl('share.emptytext', '暂无数据')}
      </div>
    );
  }
}
